﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace SocketChatServer
{
    public partial class SocketChatServer : Form
    {
        public SocketChatServer()
        {
            InitializeComponent();
            //Control.CheckForIllegalCrossThreadCalls = false;
        }
        //定义一个键值对集合，用于存储客户端的IP+端口及对应负责通信的Socket对象
        Dictionary<string, Socket> dicSocket = new Dictionary<string, Socket>();
        private void BtnStartListing_Click(object sender, EventArgs e)
        {
            try
            {
                //创建一个负责监听的socket
                Socket socketWatch = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                IPAddress ip = IPAddress.Parse(txtIP.Text);
                IPEndPoint endPoint = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));//int.Parse
                                                                                        //绑定IP+端口
                socketWatch.Bind(endPoint);
                ShowMsg("监听成功");
                //设置监听数量
                socketWatch.Listen(10);
                Thread thread = new Thread(Listen);
                thread.IsBackground = true;
                thread.Start(socketWatch);
            }
            catch
            {

            }

        }
        Socket socketCommunication;
        void Listen(object obj)
        {

            Socket socketWatch = obj as Socket;
            while (true)
            {
                try
                {
                    //等待客户端的连接，同时会创建一个与其通信的socket
                    socketCommunication = socketWatch.Accept();
                    clientCommunicationSocketList.Add(socketCommunication);
                    dicSocket.Add(socketCommunication.RemoteEndPoint.ToString(), socketCommunication);
                    //cboUsers.Items.Add(socketCommunication.RemoteEndPoint.ToString());
                    //解决跨线程访问cboUsers所导致的问题
                    if (cboUsers.InvokeRequired)
                    {
                        cboUsers.Invoke(new Action(() => { cboUsers.Items.Add(socketCommunication.RemoteEndPoint.ToString()); }), null);
                    }
                    else
                    {
                        cboUsers.Items.Add(socketCommunication.RemoteEndPoint.ToString());
                    }
                    ShowMsg(socketCommunication.RemoteEndPoint.ToString() + ":连接成功");
                    Thread thread = new Thread(Receive);
                    thread.IsBackground = true;
                    thread.Start(socketCommunication);
                }
                catch
                {

                }

            }
        }
        void Receive(object obj)
        {
            Socket socketCommunication = obj as Socket;
            byte[] buffer = new byte[1024 * 1024 * 2];
            while (true)
            {
                try
                {


                    //r表示实际接收到的字节数
                    int r = socketCommunication.Receive(buffer);
                    if (r == 0)
                    {
                        //break;
                        socketCommunication.Shutdown(SocketShutdown.Both);
                        socketCommunication.Close();

                        return;
                    }
                    string str = Encoding.UTF8.GetString(buffer, 0, r);
                    //显示消息格式：客户端IP 端口：消息
                    ShowMsg(socketCommunication.RemoteEndPoint.ToString() + ":" + str);
                }
                catch
                {

                }
            }

        }
        void ShowMsg(string str)
        {
            if (txtLog.InvokeRequired)
            {
                txtLog.Invoke(new Action<string>(s =>
                {
                    txtLog.AppendText(s + "\r\n");
                }), str);
            }
            else
            {
                //txtLog.Text = str + "\r\n"+txtLog.Text;
                txtLog.AppendText(str + "\r\n");
            }
        }

        private void BtnSend_Click(object sender, EventArgs e)
        {
            string str = txtMsg.Text.Trim();
            byte[] buffer = Encoding.UTF8.GetBytes(str);
            #region 第1种思路
            //byte[] newBuffer = new byte[buffer.Length + 1];
            //newBuffer[0] = 0;
            //Buffer.BlockCopy(buffer, 0, newBuffer, 1, buffer.Length);
            #endregion
            #region 第2种思路
            List<byte> list = new List<byte>();
            list.Add(0);
            list.AddRange(buffer);
            byte[] newBuffer = list.ToArray();
            #endregion
            string ip = cboUsers.SelectedItem.ToString();

            dicSocket[ip].Send(newBuffer);
        }

        List<Socket> clientCommunicationSocketList = new List<Socket>();
        private void BtnQunfa_Click(object sender, EventArgs e)
        {
            foreach (var socket in clientCommunicationSocketList)
            {
                if (socket.Connected)
                {
                    string str = txtMsg.Text;
                    byte[] buffer = Encoding.UTF8.GetBytes(str);
                    socket.Send(buffer);
                }
            }
        }

        private void BtnSelect_Click(object sender, EventArgs e)
        {
            OpenFileDialog ofd = new OpenFileDialog();
            ofd.InitialDirectory = @"C:\Users\LEGION\Desktop\winform\Socket网络编程\SocketChatServer\bin\Debug";
            ofd.Title = "请选择要发送的文件";
            ofd.Filter = "所有文件|*.*|word文档|*.doc";
            ofd.ShowDialog();
            txtPath.Text = ofd.FileName;
        }

        private void BtnSendFile_Click(object sender, EventArgs e)
        {
            #region 第一种思路，使用文件流读取
            //string path = txtPath.Text;
            //using (FileStream fsRead = new FileStream(path, FileMode.Open, FileAccess.Read))
            //{
            //    byte[] buffer = new byte[1024 * 1024 * 3];
            //    int r= fsRead.Read(buffer, 0, buffer.Length);
            //    List<byte> list = new List<byte>();
            //    list.Add(1);
            //    list.AddRange(buffer);
            //    byte[] newBuffer = list.ToArray();
            //    dicSocket[cboUsers.SelectedItem.ToString()].Send(newBuffer,0,r+1,SocketFlags.None);
            //}
            #endregion
            #region 第2种思路，使用File.ReadAllBytes读取
            using (OpenFileDialog ofd = new OpenFileDialog())
            {
                if (ofd.ShowDialog() != DialogResult.OK)
                {
                    return;
                }
                byte[] buffer = File.ReadAllBytes(ofd.FileName);
                byte[] newBuffer = new byte[buffer.Length + 1];
                newBuffer[0] = 1;
                Buffer.BlockCopy(buffer, 0, newBuffer, 1, buffer.Length);
                dicSocket[cboUsers.SelectedItem.ToString()].Send(newBuffer, SocketFlags.None);
            }
            #endregion
        }

        private void BtnZD_Click(object sender, EventArgs e)
        {
            byte[] buffer = new byte[1];
            buffer[0] = 2;
            dicSocket[cboUsers.SelectedItem.ToString()].Send(buffer);
        }
    }
}
